考点
代码审计
反序列化(phar反序列化 和 pop链构造)
前置知识
phar反序列化的三个前提条件
可以上传phar文件
有可以利用的魔术方法
文件操作函数的参数可控
phar文件生成
1 | //生成phar文件前需要配置php.ini |
1 | // 创建对象 exp.phar 是文件名 |
可以代替unserialize 进行反序列化操作的函数
fileatime | filectime | file_exists | file_get_contents |
file_put_contents | file | filegroup | fopen |
fileinode | filemtime | fileowner | fikeperms |
is_dir | is_executable | is_file | is_link |
is_readable | is_writable | is_writeable | parse_ini_file |
copy | unlink | stat | readfile |
魔法方法
__destruct
类对象被删除时自动调用,反正只要创建对象,都会自动调用一次
__toString
使用 echo 或者 print 进行输出时 就会自动调用
__get
读取不可访问(protected 或 private)或不存在的属性的值时会自动调用
pop链构造
1、找到可利用的地方,比如,文件包含,命令执行等地方
2、从可以利用地方回溯到可控制的地方,找到一个链条。
3、更改属性内容,先进行序列化,看看能不能达到目的。
4、能够达到目的,才进行反序列化,进行提交 有需要编码 就进行编码
解题过程
打开
两个基本的功能,文件上传和查看文件
当然,首先联想到的就是,上传图片马,文件包含getshell,事实上想太简单了,文件包含直接输出字符串,就像这样。
经过多次尝试,文件上传只能上传gif,jpg这几中文件,白名单,上传路径为/upload。文件包含只能包含,/var/www/html目录下的文件,可以包含出源代码。
获取源码
放两个关键点的代码
file.php
1 | <?php |
class.php
1 |
|
代码审计
通过审计可以得知,这道题是phar反序列化,触发点可以不用是unserialize,找到一个能够触发反序列的关键函数file_exists
,这里的$file变量可控
。
file.php 中
1 | # 创建 一个show对象 |
pop链构造
从file.php 文件中找到了反序列化触发点,接下来就要找到一个可以利用的点。
在class.php 中 Test类中的一个方法。
1 | public function file_get($value) |
简化class.php
1 |
|
接下来从class.php 文件中的 几个类中构建出 pop链。
1 | C1e4r::__destruct->Show::__toString->Test::__get |
构造pop链要从可以利用的地方放回构建。
首先Test类中要调用__get方法,那么类方法中必须调用一个不存在的属性或者私有属性,在Show类中的__toString方法中,有这么一句
$content = $this->str['str']->source;
,我们让$this->str['str']
为 Test类,那么 调用的就是$content = Test->source;
,就会触发Test类调用__get,__get中会调用get方法,get方法又会调用file_get,然后执行到file_get_contents。那要怎么才能让__toString执行呢,在C1e4r类中有一个__destruct方法,这个方法有一句echo $this->test;
,echo则会触发__toString的执行,所以我们要让$this->test 为$this->test = new Show()
,但是这里还不能这样做,在C1e4r中的__destruct方法中$this->test
要被$this->str
赋值,所以,这里,直接给$this->str = new Show()
。
上代码
注意:这里要生成phar文件,需要在 php.ini 中 让phar.readonly = On 为 Off,不然会报错
1 | $c1e4r = new C1e4r(); |
执行生成
phar后缀肯定上传不上去,改后缀上传
找到文件
phar://伪协议读取
1 | file.php?file=phar://upload/8db450d8192e8744a04cbdef20abcaf1.jpg |
得到
这个就是flag,不解码了。
总结
通过这道题,再一次巩固了反序列化的phar类型的题,不仅是phar类型,还有pop链的构造,我对pop链构造一直都不是很熟悉,说到底都还是这种类型的题做得太少,自己觉得这个题还是有难度,尤其是这么多个文件,还是去找执行反序列化的地方,刚开始,我一直以为是Test类file_get方法中的 file_get_contents函数,但是怎么想都不对,如果是它,那怎么利用呢,基本上不可能,看了别的师傅wp,才知道用phar://协议读取,file_exists函数也可以触发反序列化,学到了很多 。